home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 001-025 / disk_022 / pemacs / buffer.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  13KB  |  378 lines

  1. /*
  2.  * Buffer management.
  3.  * Some of the functions are internal,
  4.  * and some are actually attached to user
  5.  * keys. Like everyone else, they set hints
  6.  * for the display system.
  7.  */
  8. #include        <stdio.h>
  9. #include        "ed.h"
  10.  
  11. /*
  12.  * Attach a buffer to a window. The
  13.  * values of dot and mark come from the buffer
  14.  * if the use count is 0. Otherwise, they come
  15.  * from some other window.
  16.  */
  17. usebuffer(f, n)
  18. {
  19.         register BUFFER *bp;
  20.         register WINDOW *wp;
  21.         register int    s;
  22.     static char    ps[] = "Use buffer (%s): ";
  23.     char        prompt[ sizeof ps + NBUFN + 10];
  24.         char            bufn[NBUFN];
  25.  
  26.     sprintf( prompt, ps, prev_bp ? prev_bp->b_bname : "");
  27.         s=mlreply( prompt, bufn, NBUFN);
  28.     switch( s) {
  29.         case TRUE:
  30.                 if ((bp=bfind(bufn, TRUE, 0)) == NULL)
  31.                         return (FALSE);
  32.             break;
  33.  
  34.         case FALSE:
  35.             if( bp = prev_bp)
  36.                 break;
  37.         case ABORT:
  38.                     return (s);
  39.     }
  40.         if (--curbp->b_nwnd == 0) {             /* Last use.            */
  41.                 curbp->b_dotp  = curwp->w_dotp;
  42.                 curbp->b_doto  = curwp->w_doto;
  43.                 curbp->b_markp = curwp->w_markp;
  44.                 curbp->b_marko = curwp->w_marko;
  45.         }
  46.     prev_bp = curbp;
  47.         curbp = bp;                             /* Switch.              */
  48.         curwp->w_bufp  = bp;
  49.         curwp->w_linep = bp->b_linep;           /* For macros, ignored. */
  50.         curwp->w_flag |= WFMODE|WFFORCE|WFHARD; /* Quite nasty.         */
  51.         if (bp->b_nwnd++ == 0) {                /* First use.           */
  52.                 curwp->w_dotp  = bp->b_dotp;
  53.                 curwp->w_doto  = bp->b_doto;
  54.                 curwp->w_markp = bp->b_markp;
  55.                 curwp->w_marko = bp->b_marko;
  56.                 return (TRUE);
  57.         }
  58.         wp = wheadp;                            /* Look for old.        */
  59.         while (wp != NULL) {
  60.                 if (wp!=curwp && wp->w_bufp==bp) {
  61.                         curwp->w_dotp  = wp->w_dotp;
  62.                         curwp->w_doto  = wp->w_doto;
  63.                         curwp->w_markp = wp->w_markp;
  64.                         curwp->w_marko = wp->w_marko;
  65.                         break;
  66.                 }
  67.                 wp = wp->w_wndp;
  68.         }
  69.         return (TRUE);
  70. }
  71.  
  72. /*
  73.  * Dispose of a buffer, by name.
  74.  * Ask for the name. Look it up (don't get too
  75.  * upset if it isn't there at all!). Get quite upset
  76.  * if the buffer is being displayed. Clear the buffer (ask
  77.  * if the buffer has been changed). Then free the header
  78.  * line and the buffer header. Bound to "C-X K".
  79.  */
  80. killbuffer(f, n)
  81. {
  82.         register BUFFER *bp;
  83.         register BUFFER *bp1;
  84.         register BUFFER *bp2;
  85.         register int    s;
  86.         char            bufn[NBUFN];
  87.  
  88.         if ((s=mlreply("Kill buffer: ", bufn, NBUFN)) != TRUE)
  89.                 return (s);
  90.         if ((bp=bfind(bufn, FALSE, 0)) == NULL) /* Easy if unknown.     */
  91.                 return (TRUE);
  92.         if (bp->b_nwnd != 0) {                  /* Error if on screen.  */
  93.                 mlwrite("Buffer is being displayed");
  94.                 return (FALSE);
  95.         }
  96.         if ((s=bclear(bp)) != TRUE)             /* Blow text away.      */
  97.                 return (s);
  98.     if( prev_bp == bp) prev_bp = 0;        /* Dump cached buffer    */
  99.         free((char *) bp->b_linep);             /* Release header line. */
  100.         bp1 = NULL;                             /* Find the header.     */
  101.         bp2 = bheadp;
  102.         while (bp2 != bp) {
  103.                 bp1 = bp2;
  104.                 bp2 = bp2->b_bufp;
  105.         }
  106.         bp2 = bp2->b_bufp;                      /* Next one in chain.   */
  107.         if (bp1 == NULL)                        /* Unlink it.           */
  108.                 bheadp = bp2;
  109.         else
  110.                 bp1->b_bufp = bp2;
  111.         free((char *) bp);                      /* Release buffer block */
  112.         return (TRUE);
  113. }
  114.  
  115. /*
  116.  * List all of the active
  117.  * buffers. First update the special
  118.  * buffer that holds the list. Next make
  119.  * sure at least 1 window is displaying the
  120.  * buffer list, splitting the screen if this
  121.  * is what it takes. Lastly, repaint all of
  122.  * the windows that are displaying the
  123.  * list. Bound to "C-X C-B".
  124.  */
  125. listbuffers(f, n)
  126. {
  127.         register WINDOW *wp;
  128.         register BUFFER *bp;
  129.         register int    s;
  130.  
  131.         if ((s=makelist()) != TRUE)
  132.                 return (s);
  133.         if (blistp->b_nwnd == 0) {              /* Not on screen yet.   */
  134.                 if ((wp=wpopup()) == NULL)
  135.                         return (FALSE);
  136.                 bp = wp->w_bufp;
  137.                 if (--bp->b_nwnd == 0) {
  138.                         bp->b_dotp  = wp->w_dotp;
  139.                         bp->b_doto  = wp->w_doto;
  140.                         bp->b_markp = wp->w_markp;
  141.                         bp->b_marko = wp->w_marko;
  142.                 }
  143.                 wp->w_bufp  = blistp;
  144.                 ++blistp->b_nwnd;
  145.         }
  146.         wp = wheadp;
  147.         while (wp != NULL) {
  148.                 if (wp->w_bufp == blistp) {
  149.                         wp->w_linep = lforw(blistp->b_linep);
  150.                         wp->w_dotp  = lforw(blistp->b_linep);
  151.                         wp->w_doto  = 0;
  152.                         wp->w_markp = NULL;
  153.                         wp->w_marko = 0;
  154.                         wp->w_flag |= WFMODE|WFHARD;
  155.                 }
  156.                 wp = wp->w_wndp;
  157.         }
  158.         return (TRUE);
  159. }
  160.  
  161. /*
  162.  * This routine rebuilds the
  163.  * text in the special secret buffer
  164.  * that holds the buffer list. It is called
  165.  * by the list buffers command. Return TRUE
  166.  * if everything works. Return FALSE if there
  167.  * is an error (if there is no memory).
  168.  */
  169. makelist()
  170. {
  171.         register char   *cp1;
  172.         register char   *cp2;
  173.         register int    c;
  174.         register BUFFER *bp;
  175.         register LINE   *lp;
  176.         register int    nbytes;
  177.         register int    s;
  178.         register int    type;
  179.         char            b[6+1];
  180.         char            line[128];
  181.  
  182.         blistp->b_flag &= ~BFCHG;               /* Don't complain!      */
  183.         if ((s=bclear(blistp)) != TRUE)         /* Blow old text away   */
  184.                 return (s);
  185.         strcpy(blistp->b_fname, "");
  186.         if (addline("C   Size Buffer                   File") == FALSE
  187.         ||  addline("-   ---- ------                   ----") == FALSE)
  188.                 return (FALSE);
  189.         bp = bheadp;                            /* For all buffers      */
  190.         while (bp != NULL) {
  191.                 if ((bp->b_flag&BFTEMP) != 0) { /* Skip magic ones.     */
  192.                         bp = bp->b_bufp;
  193.                         continue;
  194.                 }
  195.                 cp1 = &line[0];                 /* Start at left edge   */
  196.                 if ((bp->b_flag&BFCHG) != 0)    /* "*" if changed       */
  197.                         *cp1++ = '*';
  198.                 else
  199.                         *cp1++ = ' ';
  200.                 *cp1++ = ' ';                   /* Gap.                 */
  201.                 nbytes = 0;                     /* Count bytes in buf.  */
  202.                 lp = lforw(bp->b_linep);
  203.                 while (lp != bp->b_linep) {
  204.                         nbytes += llength(lp)+1;
  205.                         lp = lforw(lp);
  206.                 }
  207.                 itoa(b, 6, nbytes);             /* 6 digit buffer size. */
  208.                 cp2 = &b[0];
  209.                 while ((c = *cp2++) != 0)
  210.                         *cp1++ = c;
  211.                 *cp1++ = ' ';                   /* Gap.                 */
  212.                 cp2 = &bp->b_bname[0];          /* Buffer name          */
  213.                 while ((c = *cp2++) != 0)
  214.                         *cp1++ = c;
  215.                 cp2 = &bp->b_fname[0];          /* File name            */
  216.                 if (*cp2 != 0) {
  217.                         while (cp1 < &line[1+1+6+1+NBUFN+1])
  218.                                 *cp1++ = ' ';           
  219.                         while ((c = *cp2++) != 0) {
  220.                                 if (cp1 < &line[128-1])
  221.                                         *cp1++ = c;
  222.                         }
  223.                 }
  224.                 *cp1 = 0;                       /* Add to the buffer.   */
  225.                 if (addline(line) == FALSE)
  226.                         return (FALSE);
  227.                 bp = bp->b_bufp;
  228.         }
  229.         return (TRUE);                          /* All done             */
  230. }
  231.  
  232. itoa(buf, width, num)
  233. register char   buf[];
  234. register int    width;
  235. register int    num;
  236. {
  237.         buf[width] = 0;                         /* End of string.       */
  238.         while (num >= 10) {                     /* Conditional digits.  */
  239.                 buf[--width] = (num%10) + '0';
  240.                 num /= 10;
  241.         }
  242.         buf[--width] = num + '0';               /* Always 1 digit.      */
  243.         while (width != 0)                      /* Pad with blanks.     */
  244.                 buf[--width] = ' ';
  245. }
  246.  
  247. /*
  248.  * The argument "text" points to
  249.  * a string. Append this line to the
  250.  * buffer list buffer. Handcraft the EOL
  251.  * on the end. Return TRUE if it worked and
  252.  * FALSE if you ran out of room.
  253.  */
  254. addline(text)
  255. char    *text;
  256. {
  257.         register LINE   *lp;
  258.         register int    i;
  259.         register int    ntext;
  260.  
  261.         ntext = strlen(text);
  262.         if ((lp=lalloc(ntext)) == NULL)
  263.                 return (FALSE);
  264.         for (i=0; i<ntext; ++i)
  265.                 lputc(lp, i, text[i]);
  266.         blistp->b_linep->l_bp->l_fp = lp;       /* Hook onto the end    */
  267.         lp->l_bp = blistp->b_linep->l_bp;
  268.         blistp->b_linep->l_bp = lp;
  269.         lp->l_fp = blistp->b_linep;
  270.         if (blistp->b_dotp == blistp->b_linep)  /* If "." is at the end */
  271.                 blistp->b_dotp = lp;            /* move it to new line  */
  272.         return (TRUE);
  273. }
  274.  
  275. /*
  276.  * Look through the list of
  277.  * buffers. Return TRUE if there
  278.  * are any changed buffers. Buffers
  279.  * that hold magic internal stuff are
  280.  * not considered; who cares if the
  281.  * list of buffer names is hacked.
  282.  * Return FALSE if no buffers
  283.  * have been changed.
  284.  */
  285. anycb()
  286. {
  287.         register BUFFER *bp;
  288.  
  289.         bp = bheadp;
  290.         while (bp != NULL) {
  291.                 if ((bp->b_flag&BFTEMP)==0 && (bp->b_flag&BFCHG)!=0)
  292.                         return (TRUE);
  293.                 bp = bp->b_bufp;
  294.         }
  295.         return (FALSE);
  296. }
  297.  
  298. /*
  299.  * Find a buffer, by name. Return a pointer
  300.  * to the BUFFER structure associated with it. If
  301.  * the named buffer is found, but is a TEMP buffer (like
  302.  * the buffer list) conplain. If the buffer is not found
  303.  * and the "cflag" is TRUE, create it. The "bflag" is
  304.  * the settings for the flags in in buffer.
  305.  */
  306. BUFFER  *
  307. bfind(bname, cflag, bflag)
  308. register char   *bname;
  309. {
  310.         register BUFFER *bp;
  311.         register LINE   *lp;
  312.  
  313.         bp = bheadp;
  314.         while (bp != NULL) {
  315.                 if (strcmp(bname, bp->b_bname) == 0) {
  316.                         if ((bp->b_flag&BFTEMP) != 0) {
  317.                                 mlwrite("Cannot select builtin buffer");
  318.                                 return (NULL);
  319.                         }
  320.                         return (bp);
  321.                 }
  322.                 bp = bp->b_bufp;
  323.         }
  324.         if (cflag != FALSE) {
  325.                 if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL)
  326.                         return (NULL);
  327.                 if ((lp=lalloc(0)) == NULL) {
  328.                         free((char *) bp);
  329.                         return (NULL);
  330.                 }
  331.                 bp->b_bufp  = bheadp;
  332.                 bheadp = bp;
  333.                 bp->b_dotp  = lp;
  334.                 bp->b_doto  = 0;
  335.                 bp->b_markp = NULL;
  336.                 bp->b_marko = 0;
  337.                 bp->b_flag  = bflag;
  338.                 bp->b_nwnd  = 0;
  339.                 bp->b_linep = lp;
  340.                 strcpy(bp->b_fname, "");
  341.                 strcpy(bp->b_bname, bname);
  342.                 lp->l_fp = lp;
  343.                 lp->l_bp = lp;
  344.         }
  345.         return (bp);
  346. }
  347.  
  348. /*
  349.  * This routine blows away all of the text
  350.  * in a buffer. If the buffer is marked as changed
  351.  * then we ask if it is ok to blow it away; this is
  352.  * to save the user the grief of losing text. The
  353.  * window chain is nearly always wrong if this gets
  354.  * called; the caller must arrange for the updates
  355.  * that are required. Return TRUE if everything
  356.  * looks good.
  357.  */
  358. bclear(bp)
  359. register BUFFER *bp;
  360. {
  361.         register LINE   *lp;
  362.         register int    s;
  363.         
  364.         if ((bp->b_flag&BFTEMP) == 0            /* Not scratch buffer.  */
  365.         && (bp->b_flag&BFCHG) != 0              /* Something changed    */
  366.         && (s=mlyesno("Discard changes")) != TRUE)
  367.                 return (s);
  368.         bp->b_flag  &= ~BFCHG;                  /* Not changed          */
  369.         while ((lp=lforw(bp->b_linep)) != bp->b_linep)
  370.                 lfree(lp);
  371.         bp->b_dotp  = bp->b_linep;              /* Fix "."              */
  372.         bp->b_doto  = 0;
  373.         bp->b_markp = NULL;                     /* Invalidate "mark"    */
  374.         bp->b_marko = 0;
  375.         return (TRUE);
  376. }
  377.  
  378.